"""
Apache Tika 客户端

提供文档文本提取功能，支持：
- Word 文档 (.doc, .docx)
- 文本文件 (.txt)
- 其他 Tika 支持的文档格式
"""

from typing import Optional
import httpx
from io import BytesIO
from loguru import logger

from src.utils.exceptions import FileProcessingError


class TikaClient:
    """Apache Tika 客户端，用于从文档中提取文本"""
    
    def __init__(self, tika_server_url: str = "http://localhost:9998"):
        """
        初始化 Tika 客户端
        
        Args:
            tika_server_url: Tika 服务器地址（默认本地 Docker 服务）
        """
        self.tika_server_url = tika_server_url.rstrip('/')
        self.timeout = 60.0  # 60秒超时
        
    async def extract_text(
        self, 
        file_content: bytes, 
        file_name: str,
        extract_metadata: bool = False
    ) -> dict:
        """
        从文档中提取文本内容
        
        Args:
            file_content: 文件字节内容
            file_name: 文件名（用于推断文件类型）
            extract_metadata: 是否提取元数据
            
        Returns:
            dict: {
                "text": "提取的文本内容",
                "metadata": {...}  # 可选，如果 extract_metadata=True
            }
            
        Raises:
            FileProcessingError: 提取失败时抛出
        """
        try:
            # 使用 Tika /tika endpoint 提取文本
            url = f"{self.tika_server_url}/tika"
            
            headers = {
                "Accept": "text/plain",
                "Content-Type": "application/octet-stream"
            }
            
            async with httpx.AsyncClient(timeout=self.timeout) as client:
                logger.info(f"调用 Tika 提取文本 | 文件: {file_name} | 大小: {len(file_content)} 字节")
                
                response = await client.put(
                    url,
                    content=file_content,
                    headers=headers
                )
                
                if response.status_code != 200:
                    error_msg = f"Tika 返回错误状态码: {response.status_code}, 详情: {response.text}"
                    logger.error(error_msg)
                    raise FileProcessingError(error_msg)
                
                text = response.text
                logger.info(f"Tika 提取文本成功 | 文件: {file_name} | 文本长度: {len(text)} 字符")
                
                result = {"text": text}
                
                # 如果需要元数据，再发一次请求
                if extract_metadata:
                    metadata = await self._extract_metadata(file_content, file_name)
                    result["metadata"] = metadata
                
                return result
                
        except httpx.RequestError as e:
            error_msg = f"Tika 服务请求失败: {str(e)}"
            logger.error(error_msg)
            raise FileProcessingError(error_msg)
        except Exception as e:
            error_msg = f"Tika 文本提取失败: {str(e)}"
            logger.error(error_msg)
            raise FileProcessingError(error_msg)
    
    async def _extract_metadata(self, file_content: bytes, file_name: str) -> dict:
        """
        提取文档元数据
        
        Args:
            file_content: 文件字节内容
            file_name: 文件名
            
        Returns:
            dict: 元数据字典
        """
        try:
            url = f"{self.tika_server_url}/meta"
            
            headers = {
                "Accept": "application/json",
                "Content-Type": "application/octet-stream"
            }
            
            async with httpx.AsyncClient(timeout=self.timeout) as client:
                response = await client.put(
                    url,
                    content=file_content,
                    headers=headers
                )
                
                if response.status_code == 200:
                    return response.json()
                else:
                    logger.warning(f"Tika 元数据提取失败: {response.status_code}")
                    return {}
                    
        except Exception as e:
            logger.warning(f"Tika 元数据提取异常: {e}")
            return {}
    
    async def check_health(self) -> bool:
        """
        检查 Tika 服务是否健康
        
        Returns:
            bool: 服务是否可用
        """
        try:
            async with httpx.AsyncClient(timeout=5.0) as client:
                response = await client.get(f"{self.tika_server_url}/tika")
                return response.status_code == 200
        except Exception as e:
            logger.warning(f"Tika 健康检查失败: {e}")
            return False
    
    @staticmethod
    def is_supported_format(file_extension: str) -> bool:
        """
        检查文件格式是否支持 Tika 提取
        
        Args:
            file_extension: 文件扩展名（带点，如 .docx）
            
        Returns:
            bool: 是否支持
        """
        supported_formats = {
            # Word 文档
            '.doc', '.docx', '.dot', '.dotx',
            # 文本文件
            '.txt', '.text',
            # Rich Text
            '.rtf',
            # OpenDocument
            '.odt', '.ott',
            # HTML
            '.html', '.htm',
            # Markdown
            '.md', '.markdown',
            # Excel
            '.xlsx', '.xlsm',
            # CSV
            '.csv'
        }
        return file_extension.lower() in supported_formats



